package com.aaa.demo01Thread;

import java.util.concurrent.TimeUnit;

/**
 * @author Richard Wang
 * @date 2025/6/24 23:03
 */
class MyData {
    //int number = 0;
    volatile int number = 0;

    public void addTo60() {
        this.number = 60;
    }

    //number前加了volatile，但其不保证原子性
    public void addPlusPlus() {
        this.number++;
    }
}

/*
1、验证volatile 的可见性
    1.1假如 int number=0;,number变量之前没有添加volatile关键字修饰，没有可见性

    1.2volatile不保证原子性
 */
public class VolatileDemo {
    public static void main(String[] args) {
        MyData myData = new MyData();
        for (int i = 1; i <= 20; i++) {
            new Thread(() -> {
                for (int j = 0; j < 1000; j++) {
                    myData.addPlusPlus();
                }
            }, String.valueOf(i)).start();
        }
        //需要等待前面20个线程全部执行完毕，再用main线程取出最终结果
        while (Thread.activeCount() > 2) {//默认有两个线程，1是main线程，2是后台gc线程
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName()+"final value:"+ myData.number);
    }

    //volatile可以保证可见性，及时通知其他线程，主内存数据已被修改。
    private static void volatileExample() {
        MyData myData = new MyData();//资源类
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t come in");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            myData.addTo60();
            System.out.println(Thread.currentThread().getName() + "\t update number value" + myData.number);
        }, "AAA").start();

        //第2个线程是main线程
        while (myData.number == 0) {
            //main线程就一直等待循环，直到number值不再等于0
        }

        System.out.println(Thread.currentThread().getName() + "\t mission over,main get number value:" + myData.number);
    }
}
